package net.jkdmanager.server.services.agents;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import net.jkdmanager.common.api.messages.AgentStatusMessage;
import net.jkdmanager.common.services.messaging.MessageListener;
import net.jkdmanager.server.model.AgentStatus;
import net.jkdmanager.server.services.applicationstatuses.ApplicationStatusesService;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class AgentStatusesServiceImpl implements AgentStatusesService, MessageListener {

	private static Log log = LogFactory.getLog(AgentStatusesServiceImpl.class);
	
	@Autowired
	private ApplicationStatusesService applicationStatusesService;
	
	private Map<String, AgentStatus> agentStatuses = new ConcurrentHashMap<String, AgentStatus>();
	
	private long maximumInactivityDelayInSeconds = 120;  
	
	public void receiveMessage(Serializable genericMessage) {
		
		if (genericMessage instanceof AgentStatusMessage) {
			AgentStatusMessage message = (AgentStatusMessage)genericMessage;
			String agentId = message.getAgentId();
			//System.out.println("Pinged by " + agentId);
			AgentStatus agentStatus = agentStatuses.get(agentId);
			if (agentStatus != null) {
				agentStatus.setLastPing(new Date());
			} else {
				agentStatus = new AgentStatus();
				agentStatus.setAgentId(agentId);
				agentStatus.setLastPing(new Date());
				agentStatuses.put(agentId, agentStatus);
			}
		}
		
	}

	@Scheduled(fixedRate=1000)
	public void disconnectInactiveAgents() {
		for (AgentStatus agentStatus : agentStatuses.values()) {
			if (agentStatus.getLastPing().getTime() < System.currentTimeMillis() - maximumInactivityDelayInSeconds * 1000) {
				agentStatuses.remove(agentStatus.getAgentId());
				applicationStatusesService.agentDisconnected(agentStatus.getAgentId());
				log.warn(
						String.format("Agent %s not pinged in specified time interval. It is supposed to be down.", agentStatus.getAgentId()));
			}
		}
	}
	
	public List<AgentStatus> getAgentStatuses() {
		return new ArrayList<AgentStatus>(agentStatuses.values());
	}
	
}
